package dk.mirasola.systemtraining.bridgewidgets.client.ui.distributionfiltereditor;

import com.google.gwt.cell.client.AbstractCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellTree;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.gwt.view.client.TreeViewModel;
import dk.mirasola.systemtraining.bridgewidgets.client.i18n.EditorTexts;
import dk.mirasola.systemtraining.bridgewidgets.client.ui.RenderUtil;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.Seat;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.Suit;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.CompareOperator;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.DistributionFilterGroup;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.DistributionFilterGroupItem;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.FitDistributionFilter;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.GroupItem;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.HcpSeatDistributionFilter;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.HcpSuitDistributionFilter;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.LogicOperatorGroupItem;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.MajorMinorDistributionFilter;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.NTDistributionFilter;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.ShapeDistributionFilter;
import dk.mirasola.systemtraining.bridgewidgets.shared.model.distributionfiltertree.ShapeTypeDistributionFilter;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DistributionFilterTreeEditor extends Composite {
    private static EditorTexts editorTexts = GWT.create(EditorTexts.class);


    interface DistributionFilterTreeEditorUIBinder extends UiBinder<Widget, DistributionFilterTreeEditor> {
    }

    private static DistributionFilterTreeEditorUIBinder uiBinder = GWT.create(DistributionFilterTreeEditorUIBinder.class);

    interface ShapeDistributionFilterEditorDriver extends SimpleBeanEditorDriver<ShapeDistributionFilter, ShapeDistributionFilterEditor> {
    }

    private static ShapeDistributionFilterEditorDriver shapeDistributionFilterEditorDriver = GWT.create(ShapeDistributionFilterEditorDriver.class);

    interface ShapeTypeDistributionFilterEditorDriver extends SimpleBeanEditorDriver<ShapeTypeDistributionFilter, ShapeTypeDistributionFilterEditor> {
    }

    private static ShapeTypeDistributionFilterEditorDriver shapeTypeDistributionFilterEditorDriver = GWT.create(ShapeTypeDistributionFilterEditorDriver.class);

    interface DistributionFilterGroupEditorDriver extends SimpleBeanEditorDriver<DistributionFilterGroup, DistributionFilterGroupEditor> {
    }

    private static DistributionFilterGroupEditorDriver distributionFilterGroupEditorDriver = GWT.create(DistributionFilterGroupEditorDriver.class);

    interface LogicOperatorGroupItemEditorDriver extends SimpleBeanEditorDriver<LogicOperatorGroupItem, LogicOperatorGroupItemEditor> {
    }

    private static LogicOperatorGroupItemEditorDriver logicOperatorGroupItemEditorDriver = GWT.create(LogicOperatorGroupItemEditorDriver.class);

    interface HcpSeatDistributionFilterEditorDriver extends SimpleBeanEditorDriver<HcpSeatDistributionFilter, HcpSeatDistributionFilterEditor> {
    }

    private static HcpSeatDistributionFilterEditorDriver hcpSeatDistributionFilterEditorDriver = GWT.create(HcpSeatDistributionFilterEditorDriver.class);

    interface HcpSuitDistributionFilterEditorDriver extends SimpleBeanEditorDriver<HcpSuitDistributionFilter, HcpSuitDistributionFilterEditor> {
    }

    private static HcpSuitDistributionFilterEditorDriver hcpSuitDistributionFilterEditorDriver = GWT.create(HcpSuitDistributionFilterEditorDriver.class);

    interface MajorMinorDistributionFilterEditorDriver extends SimpleBeanEditorDriver<MajorMinorDistributionFilter, MajorMinorDistributionFilterEditor> {
    }

    private static MajorMinorDistributionFilterEditorDriver majorMinorDistributionFilterEditorDriver = GWT.create(MajorMinorDistributionFilterEditorDriver.class);

    interface NTDistributionFilterEditorDriver extends SimpleBeanEditorDriver<NTDistributionFilter, NTDistributionFilterEditor> {
    }

    private static NTDistributionFilterEditorDriver ntDistributionFilterEditorDriver = GWT.create(NTDistributionFilterEditorDriver.class);

    interface FitDistributionFilterEditorDriver extends SimpleBeanEditorDriver<FitDistributionFilter, FitDistributionFilterEditor> {
    }

    private static FitDistributionFilterEditorDriver fitDistributionFilterEditorDriver = GWT.create(FitDistributionFilterEditorDriver.class);

    private class GroupItemCell extends AbstractCell<GroupItem> {
        @Override
        public void render(Context context, GroupItem value, SafeHtmlBuilder sb) {
            if (value instanceof DistributionFilterGroupItem) {
                DistributionFilterGroupItem distributionFilterGroupItem = (DistributionFilterGroupItem) value;
                if (distributionFilterGroupItem.getInverted()) {
                    SafeHtmlBuilder tmpBuilder = new SafeHtmlBuilder();
                    renderDistributionFilterGroup(distributionFilterGroupItem, tmpBuilder);
                    sb.append(editorTexts.invertedDistributionFilterTreeNode(tmpBuilder.toSafeHtml()));
                } else {
                    renderDistributionFilterGroup(distributionFilterGroupItem, sb);
                }
            } else if (value instanceof LogicOperatorGroupItem) {
                LogicOperatorGroupItem logicOperatorGroupItem = (LogicOperatorGroupItem) value;
                sb.append(RenderUtil.renderLogicOperator(logicOperatorGroupItem.getLogicOperator()));
            } else {
                throw new RuntimeException("Unknow group item: " + value);
            }
        }

        private void renderDistributionFilterGroup(DistributionFilterGroupItem distributionFilterGroupItem, SafeHtmlBuilder sb) {
            if (distributionFilterGroupItem instanceof DistributionFilterGroup) {
                DistributionFilterGroup group = (DistributionFilterGroup) distributionFilterGroupItem;
                sb.append(editorTexts.distributionFilterGroupTreeNode(SafeHtmlUtils.fromString(group.getName())));
            } else if (distributionFilterGroupItem instanceof ShapeDistributionFilter) {
                ShapeDistributionFilter shapeDistributionFilter = (ShapeDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.shapeDistributionFilterTreeNode(
                        RenderUtil.renderShape(shapeDistributionFilter.getShape()),
                        RenderUtil.renderSeatLowercase(shapeDistributionFilter.getSeat())));
            } else if (distributionFilterGroupItem instanceof HcpSeatDistributionFilter) {
                HcpSeatDistributionFilter hcpSeatDistributionFilter = (HcpSeatDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.hcpSeatDistributionFilterTreeNode(
                        RenderUtil.renderHcpInterval(hcpSeatDistributionFilter.getHcpInterval()),
                        RenderUtil.renderSeatsLowercase(hcpSeatDistributionFilter.getSeats(), ",")));
            } else if (distributionFilterGroupItem instanceof HcpSuitDistributionFilter) {
                HcpSuitDistributionFilter hcpSuitDistributionFilter = (HcpSuitDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.hcpSuitDistributionFilterTreeNode(
                        RenderUtil.renderHcpInterval(hcpSuitDistributionFilter.getHcpInterval()),
                        RenderUtil.renderSeatLowercase(hcpSuitDistributionFilter.getSeat()),
                        RenderUtil.renderSuits(hcpSuitDistributionFilter.getSuits(), ",")));
            } else if (distributionFilterGroupItem instanceof MajorMinorDistributionFilter) {
                MajorMinorDistributionFilter majorMinorDistributionFilter = (MajorMinorDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.majorMajorDistributionFilterTreeNode(
                        RenderUtil.renderCardsCountInterval(majorMinorDistributionFilter.getMajorCardsCountInterval()),
                        RenderUtil.renderCardsCountInterval(majorMinorDistributionFilter.getMinorCardsCountInterval()),
                        RenderUtil.renderSeatLowercase(majorMinorDistributionFilter.getSeat())));
            } else if (distributionFilterGroupItem instanceof NTDistributionFilter) {
                NTDistributionFilter ntDistributionFilter = (NTDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.ntDistributionFilterTreeNode(
                        RenderUtil.renderHcpInterval(ntDistributionFilter.getHcpInterval()),
                        RenderUtil.renderSeatLowercase(ntDistributionFilter.getSeat())));
                if (ntDistributionFilter.getFiveCardMajorsAllowed() || ntDistributionFilter.getSixCardMinorsAllowed()) {
                    sb.append(SafeHtmlUtils.fromTrustedString(" ("));
                }
                if (ntDistributionFilter.getFiveCardMajorsAllowed()) {
                    sb.append(5);
                    sb.append(RenderUtil.renderSuit(Suit.SPADE));
                    sb.append(SafeHtmlUtils.fromTrustedString("/"));
                    sb.append(RenderUtil.renderSuit(Suit.HEART));
                }
                if (ntDistributionFilter.getFiveCardMajorsAllowed() && ntDistributionFilter.getSixCardMinorsAllowed()) {
                    sb.append(SafeHtmlUtils.fromTrustedString(","));
                }
                if (ntDistributionFilter.getSixCardMinorsAllowed()) {
                    sb.append(6);
                    sb.append(RenderUtil.renderSuit(Suit.DIAMOND));
                    sb.append(SafeHtmlUtils.fromTrustedString("/"));
                    sb.append(RenderUtil.renderSuit(Suit.CLUB));
                }
                if (ntDistributionFilter.getFiveCardMajorsAllowed() || ntDistributionFilter.getSixCardMinorsAllowed()) {
                    sb.append(SafeHtmlUtils.fromTrustedString(")"));
                }
            } else if (distributionFilterGroupItem instanceof ShapeTypeDistributionFilter) {
                ShapeTypeDistributionFilter shapeTypeDistributionFilter = (ShapeTypeDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.shapeTypeDistributionFilterTreeNode(
                        RenderUtil.renderShapeType(shapeTypeDistributionFilter.getShapeType()),
                        RenderUtil.renderSeatLowercase(shapeTypeDistributionFilter.getSeat())));
            } else if (distributionFilterGroupItem instanceof FitDistributionFilter) {
                FitDistributionFilter fitDistributionFilter = (FitDistributionFilter) distributionFilterGroupItem;
                sb.append(editorTexts.fitDistributionFilterTreeNode(
                        RenderUtil.renderSuits(fitDistributionFilter.getSuits(), ","),
                        RenderUtil.renderSeatsLowercase(fitDistributionFilter.getSeats(), ","),
                        RenderUtil.renderComparaOperator(fitDistributionFilter.getComparator()),
                        fitDistributionFilter.getTotalCards()));
            } else {
                throw new RuntimeException("Unknow distribution filter group item: " + distributionFilterGroupItem);
            }
        }
    }

    private class DistributionFilterTreeViewModel implements TreeViewModel {
        @Override
        public <T> NodeInfo<?> getNodeInfo(T value) {
            if (value == null) {
                // root
                ListDataProvider<GroupItem> dataProvider = new ListDataProvider<GroupItem>();
                dataProvider.getList().add(tree);
                return new DefaultNodeInfo<GroupItem>(dataProvider, new GroupItemCell(), selectionModel, null);
            } else if (value instanceof DistributionFilterGroup) {
                DistributionFilterGroup group = (DistributionFilterGroup) value;
                ListDataProvider<GroupItem> dataProvider = new ListDataProvider<GroupItem>(group.getGroupItems());
                dataProviderMap.put(group, dataProvider);
                return new DefaultNodeInfo<GroupItem>(dataProvider, new GroupItemCell(), selectionModel, null);
            } else {
                throw new RuntimeException("unknown type: " + value);
            }
        }

        @Override
        public boolean isLeaf(Object value) {
            return value != null && !(value instanceof DistributionFilterGroup);
        }
    }

    @UiField(provided = true)
    CellTree distributionFilterTree;
    @UiField
    ScrollPanel editorPanel;
    @UiField
    ToolbarImage addTreeNode;
    @UiField
    ToolbarImage deleteTreeNode;
    @UiField
    ToolbarImage moveUpTreeNode;
    @UiField
    ToolbarImage moveDownTreeNode;

    private DistributionFilterGroup original = null;
    private DistributionFilterGroup tree = null;
    private Map<DistributionFilterGroup, ListDataProvider<GroupItem>> dataProviderMap = new HashMap<DistributionFilterGroup, ListDataProvider<GroupItem>>();
    private SingleSelectionModel<GroupItem> selectionModel = new SingleSelectionModel<GroupItem>();
    private SimpleBeanEditorDriver driver = null;

    public DistributionFilterTreeEditor(final DistributionFilterGroup tree) {
        if (tree == null) {
            throw new NullPointerException();
        }
        original = tree;
        this.tree = tree.copy();
        CellTree.Resources resources = GWT.create(CellTree.BasicResources.class);
        distributionFilterTree = new CellTree(new DistributionFilterTreeViewModel(), null, resources);
        distributionFilterTree.getRootTreeNode().setChildOpen(0, true, false);

        initWidget(uiBinder.createAndBindUi(this));

        initSelectionModel();

        initToolbar();
    }

    private void initToolbar() {
        addTreeNode.addMouseOverHandler(new MouseOverHandler() {
            @Override
            public void onMouseOver(MouseOverEvent event) {
                if (addTreeNode.isEnabled()) {
                    PopupPanel addDistributionFilterPopup = new PopupPanel(true, true);
                    FlowPanel popupPanel = new FlowPanel();
                    addDistributionFilterPopup.setWidget(popupPanel);
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addGroupLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new DistributionFilterGroup(editorTexts.addGroupName());
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addHcpSuitLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new HcpSuitDistributionFilter();
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addHcpSeatLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new HcpSeatDistributionFilter();
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addShapeLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new ShapeDistributionFilter();
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addShapeTypeLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new ShapeTypeDistributionFilter();
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addFitLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            FitDistributionFilter fitDistributionFilter = new FitDistributionFilter();
                            fitDistributionFilter.getSuits().add(Suit.SPADE);
                            fitDistributionFilter.getSeats().add(Seat.NORTH);
                            fitDistributionFilter.setComparator(CompareOperator.LESS_THAN_OR_EQUAL);
                            fitDistributionFilter.setTotalCards(5);
                            return fitDistributionFilter;
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addNTLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new NTDistributionFilter();
                        }
                    }));
                    popupPanel.add(createAddDistributionFilterPopupLabel(addDistributionFilterPopup, editorTexts.addMajorMinorLabel(), new DistributionFilterGroupItemCreator() {
                        @Override
                        public DistributionFilterGroupItem createDistributionFilterGroupItem() {
                            return new MajorMinorDistributionFilter();
                        }
                    }));

                    addDistributionFilterPopup.showRelativeTo(addTreeNode);
                }
            }
        });

        deleteTreeNode.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                GroupItem removeItem = selectionModel.getSelectedObject();
                DistributionFilterGroup parent = removeItem.getGroup();
                List<GroupItem> items = getParentGroupItems(removeItem);

                selectionModel.setSelected(parent, true);

                if (items.size() > 1) {
                    int removeIdx = items.indexOf(removeItem);
                    if (removeIdx == 0) {
                        items.remove(1);
                        items.remove(0);
                    } else {
                        items.remove(removeIdx);
                        items.remove(removeIdx - 1);
                    }
                } else {
                    items.remove(0);
                }

            }
        });

        moveUpTreeNode.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                GroupItem moveUpItem = selectionModel.getSelectedObject();
                List<GroupItem> items = getParentGroupItems(moveUpItem);

                int idx = items.indexOf(moveUpItem);
                items.remove(idx);
                GroupItem swapItem = items.remove(idx - 2);

                items.add(idx - 2, moveUpItem);
                items.add(idx, swapItem);
            }
        });

        moveDownTreeNode.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                GroupItem moveUpItem = selectionModel.getSelectedObject();
                List<GroupItem> items = getParentGroupItems(moveUpItem);

                int idx = items.indexOf(moveUpItem);
                GroupItem swapItem = items.remove(idx + 2);
                items.remove(idx);

                items.add(idx, swapItem);
                items.add(idx + 2, moveUpItem);
            }
        });
    }

    private List<GroupItem> getParentGroupItems(GroupItem groupItem) {
        List<GroupItem> items = null;
        ListDataProvider<GroupItem> listDataProvider = dataProviderMap.get(groupItem.getGroup());
        if (listDataProvider != null) {
            items = listDataProvider.getList();
        } else {
            items = groupItem.getGroup().getGroupItems();
        }
        return items;
    }

    private interface DistributionFilterGroupItemCreator {
        DistributionFilterGroupItem createDistributionFilterGroupItem();
    }

    private Label createAddDistributionFilterPopupLabel(final PopupPanel popupPanel, String text, final DistributionFilterGroupItemCreator creator) {
        final Label label = new Label(text);
        label.setStylePrimaryName("distributionFilterTree-new-distributionfilter-label");
        label.addMouseOverHandler(new MouseOverHandler() {
            @Override
            public void onMouseOver(MouseOverEvent event) {
                label.addStyleDependentName("mouseover");
            }
        });
        label.addMouseOutHandler(new MouseOutHandler() {
            @Override
            public void onMouseOut(MouseOutEvent event) {
                label.removeStyleDependentName("mouseover");
            }
        });
        label.addClickHandler(new ClickHandler() {
            @Override
            public void onClick(ClickEvent event) {
                popupPanel.hide();

                GroupItem selection = selectionModel.getSelectedObject();
                if (!(selection instanceof DistributionFilterGroup)) {
                    return;
                }

                DistributionFilterGroupItem newItem = creator.createDistributionFilterGroupItem();
                ListDataProvider<GroupItem> listDataProvider = dataProviderMap.get(selection);
                List<GroupItem> groupItems;
                if (listDataProvider != null) {
                    groupItems = listDataProvider.getList();
                } else {
                    groupItems = ((DistributionFilterGroup) selection).getGroupItems();
                }
                if (groupItems.size() > 0) {
                    groupItems.add(new LogicOperatorGroupItem());
                }
                groupItems.add(newItem);

                selectionModel.setSelected(newItem, true);
            }
        });
        return label;
    }

    private void initSelectionModel() {
        selectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
            @Override
            public void onSelectionChange(SelectionChangeEvent event) {
                editorPanel.clear();
                if (driver != null) {
                    GroupItem groupItem = (GroupItem) driver.flush();
                    ListDataProvider dataProvider = dataProviderMap.get(groupItem.getGroup());
                    if (dataProvider != null) {
                        dataProvider.refresh();
                    }
                }

                GroupItem selection = selectionModel.getSelectedObject();
                updateToolbar(selection);
                if (selection == null) {
                    driver = null;
                    return;
                }

                edit(selection);
            }

            private void updateToolbar(GroupItem selection) {
                addTreeNode.setEnabled(selection instanceof DistributionFilterGroup);
                deleteTreeNode.setEnabled(!(selection instanceof LogicOperatorGroupItem) && selection.getGroup() != null);
                moveUpTreeNode.setEnabled(!(selection instanceof LogicOperatorGroupItem) &&
                        selection.getGroup() != null &&
                        selection.getGroup().getGroupItems().indexOf(selection) > 0);
                moveDownTreeNode.setEnabled(!(selection instanceof LogicOperatorGroupItem) &&
                        selection.getGroup() != null &&
                        selection.getGroup().getGroupItems().lastIndexOf(selection) < selection.getGroup().getGroupItems().size() - 1);
            }

            private void edit(GroupItem groupItem) {
                Editor editor = null;
                driver = null;
                if (groupItem instanceof ShapeDistributionFilter) {
                    driver = shapeDistributionFilterEditorDriver;
                    editor = new ShapeDistributionFilterEditor();
                } else if (groupItem instanceof DistributionFilterGroup) {
                    driver = distributionFilterGroupEditorDriver;
                    editor = new DistributionFilterGroupEditor();
                } else if (groupItem instanceof LogicOperatorGroupItem) {
                    driver = logicOperatorGroupItemEditorDriver;
                    editor = new LogicOperatorGroupItemEditor();
                } else if (groupItem instanceof HcpSeatDistributionFilter) {
                    driver = hcpSeatDistributionFilterEditorDriver;
                    editor = new HcpSeatDistributionFilterEditor();
                } else if (groupItem instanceof HcpSuitDistributionFilter) {
                    driver = hcpSuitDistributionFilterEditorDriver;
                    editor = new HcpSuitDistributionFilterEditor();
                } else if (groupItem instanceof MajorMinorDistributionFilter) {
                    driver = majorMinorDistributionFilterEditorDriver;
                    editor = new MajorMinorDistributionFilterEditor();
                } else if (groupItem instanceof NTDistributionFilter) {
                    driver = ntDistributionFilterEditorDriver;
                    editor = new NTDistributionFilterEditor();
                } else if (groupItem instanceof ShapeTypeDistributionFilter) {
                    driver = shapeTypeDistributionFilterEditorDriver;
                    editor = new ShapeTypeDistributionFilterEditor();
                } else if (groupItem instanceof FitDistributionFilter) {
                    driver = fitDistributionFilterEditorDriver;
                    editor = new FitDistributionFilterEditor();
                }

                if (editor != null && driver != null) {
                    driver.initialize(editor);
                    driver.edit(groupItem);
                    editorPanel.setWidget((Widget) editor);
                }
            }
        });
    }

    public DistributionFilterGroup flush() {
        if (driver != null) {
            driver.flush();
        }
        return tree.copy();
    }
}
